<template>
{{#if ctrl.psSysPFPlugin}}
    {{> @macro/plugins/widget/widget-use.hbs appPlugin=ctrl.psSysPFPlugin}}
{{else}}
  <div :class="classNames" :id="controlID">
    {{#if (neq ctrl.calendarStyle 'TIMELINE')}}
    <div class="control-header app-control-calendar__header">
        <div class="app-control-calendar__header__legends">
            <template v-for="item in model.calendarItems">
                <div :class="{ 'app-control-calendar__header__legend': true, [item.itemType]: true, 'is-disabled': !store.isShowLegend[item.itemType] }" @click="()=>legendTrigger(item.itemType)">
                    <div class="lengend__icon" :style="'background:' + item.bKColor"></div>
                    <span class="lengend__text" :style="'color:' + item.color">\{{item.name}}</span>
                </div>
            </template>
        </div>
    </div>    
    {{/if}}    
    <div class="control-content app-control-calendar__content">
      {{#if (eq ctrl.calendarStyle 'TIMELINE')}}
      <AppCalendarTimeline :name="model.codeName" :store="store" style="{{#if ctrl.width}}width: {{ctrl.width}}px;{{/if}}{{#if ctrl.height}}height: {{ctrl.height}}px;{{/if}}" @click-event="ClickTimelineEvent">
      {{#each ctrl.psSysCalendarItems as |calendarItem|}}
        {{#if calendarItem.psLayoutPanel}}
        <template #default="{ item }">
            {{> @macro/widgets/panel-detail/panel.hbs ctrl=calendarItem.psLayoutPanel props=":isLoadDefault='true'
            :data='item'"}}
        </template>
        {{/if}}      
      {{/each}}
      </AppCalendarTimeline>
      {{else}}
      <AppCalendar ref="calendar" :name="model.codeName" :class="classNames" :store="store" style="{{#if ctrl.width}}width: {{ctrl.width}}px;{{/if}}{{#if ctrl.height}}height: {{ctrl.height}}px;{{/if}}" @get-events="getEvents" @click-event="clickEvent" @render-event="renderEvent"></AppCalendar>
      {{/if}}
    </div>
  </div>
{{/if}}
</template>
<script setup lang="ts">
// 基于template/src/widgets/\{{appEntities}}/\{{ctrls@CALENDAR}}-calendar/\{{spinalCase ctrl.codeName}}-calendar.vue.hbs生成
{{> @macro/plugins/widget/widget-import.hbs ctrl=ctrl}}
{{#if (eq ctrl.calendarStyle 'TIMELINE')}}
import { AppCalendarTimeline } from '@components/widgets/calendar-timeline';
{{else}}
import { AppCalendar } from '@components/widgets/calendar';
{{/if}}  
{{#each ctrl.psSysCalendarItems as |calendarItem|}}
{{#if calendarItem.psLayoutPanel}}
import {{calendarItem.psLayoutPanel.codeName}}Panel from '@widgets/{{spinalCase calendarItem.psLayoutPanel.psAppDataEntity.codeName}}/{{spinalCase calendarItem.psLayoutPanel.codeName}}-panel/{{spinalCase calendarItem.psLayoutPanel.codeName}}-panel.vue';
{{/if}}
{{/each}}
import { model } from "./{{spinalCase ctrl.codeName}}-calendar-model";
import { IContext, IParam, createUUID, ILoadingHelper, ControlVOBase, CalendarActionType, ICtrlDataAction, ICalendarAbility, ICalendarController, ICalendarControllerParams, ICalendarStore, CalendarController, IViewCtx } from "@/core";
import { useNavParamsBind, useEventBind, getCtrlClassNames, {{#each ctrl.psSysCalendarItems as |calendarItem|}}{{#if calendarItem.psLayoutPanel}}handleCtrlInit, handleCtrlAction, handleCtrlDestroy,{{/if}}{{/each}} } from '@/hooks/use-ctrl';
import { createVNode,render, Ref } from 'vue';   
import CalendarService from '@/core/modules/ctrl-service/calendar-service';
import { {{pascalCase ctrl.name}}ControlVO } from './{{spinalCase ctrl.codeName}}-calendar-vo';
import { AppContextMenuContainer } from '@components/common/context-menu-container';

// 输入参数
{{> @macro/widgets/ctrl/ctrl-props.hbs
    props="openView?: Function;
    newView?: Function;
    actions: ICtrlDataAction;    
    selectFirstDefault?: boolean;
    "
}}

// emit
{{> @macro/common/emit.hbs name="ctrl" actionType="CalendarActionType" ability="ICalendarAbility"}}

// 部件样式名
const classNames = computed(() => {
return getCtrlClassNames(model, props);
});

const calendar:Ref<IParam | null>= ref(null);


const controlID = 'id' + createUUID();

// 部件服务
const ctrlService = new CalendarService<ControlVOBase[]>({{pascalCase ctrl.name}}ControlVO, model.entityCodeName, {model})

const params: ICalendarControllerParams<CalendarActionType, ICalendarAbility> = {
    name: props.name,    
    model,
    evt,
    controlID,    
    pLoadingHelper: props.pLoadingHelper,    
    actions: props.actions,
    openView: props.openView,
    newView: props.newView,
    closeView: props.closeView,
    selectFirstDefault: props.selectFirstDefault,
    ctrlService: ctrlService,
    pViewCtx: props.pViewCtx,
    handler: (data: ICalendarStore) => { return reactive(data); }
};
//  控制器
{{> @macro/common/controller.hbs name="ctrl" IController="ICalendarController" store="ICalendarStore" ability="ICalendarAbility" controller="CalendarController"}}

{{#if (neq ctrl.calendarStyle 'TIMELINE')}}
// fullCalendar load时自己刷新日程
evt.on("ctrlAction", (controlName: string, action: CalendarActionType, data: any) => {
    if (action === 'refetchEvents') {
        refreshFullCalendar();
    }
});

// 计算日历日程样式
const handleEventStyle = (info: IParam) => {
    if (!info) {
        return;
    }
    if (calendar?.value?.fullCalendarRef) {
    const fullCalendarRef = calendar.value.fullCalendarRef;
    const data = info.event.extendedProps.$DO;
    let calendarItem = model.calendarItems.find((_item: IParam) => {
        return _item.itemType == data.itemType;
    });
    const cssName = calendarItem?.cssName;
    const calendarEvents: any[] = fullCalendarRef.getEvents().filter((event: any) => {
        return event.extendedProps.$DO[controller.getEventKey(event.extendedProps.$DO)!] === data[controller.getEventKey(info.event.extendedProps.$DO)!];
    });
    if (cssName && calendarEvents.length > 0) {
        calendarEvents.forEach((event: any) => {
            const classNames: any[] = [...event.classNames];
            if (classNames.findIndex((className: any) => { return className == cssName; }) === -1) {
                classNames.push(cssName);
                event.setProp('classNames', classNames);
            }
        })
    }
    }
}

// 刷新fullCalendar大小
const refreshFullCalendarSize = () => {
    if (calendar?.value?.fullCalendarRef) {
        const fullCalendarRef = calendar.value.fullCalendarRef;
        fullCalendarRef.updateSize();
    }
}

// fullCalendar重新获取日程
const refreshFullCalendar = () => {
    if (calendar?.value?.fullCalendarRef) {
        const fullCalendarRef = calendar.value.fullCalendarRef;
        fullCalendarRef.refetchEvents();
    }      
}

// 事件id
const eventid: Ref<string> = ref('');    

// 处理日历日程选中样式
const handleEventSelectStyle = ($event: any)=> {
    if (calendar?.value?.fullCalendarRef) {
        const fullCalendarRef = calendar.value.fullCalendarRef;
        if (!fullCalendarRef) {
            return;
        }
        const findApis = (id: any) => {
            if (!id) {
                return [];
            }
            return fullCalendarRef.getEvents().filter((event: any) => {
                return event.extendedProps.$DO[controller.getEventKey(event.extendedProps.$DO)!] === id;
            });
        }
        const eventId: any = $event.event.extendedProps.$DO[controller.getEventKey($event.event.extendedProps.$DO)!];
        const eventApis: any[] = findApis(eventId);
        eventApis.forEach((api: any) => {
            const classNames: any[] = [...api.classNames];
            if (classNames.findIndex((className: any) => { return className == 'selected-event'; }) === -1) {
                classNames.push('selected-event');
            }
            api.setProp('classNames', classNames);
        })
        if (props.selectFirstDefault && eventid.value != eventId || (!props.selectFirstDefault)) {
            const _eventApis: any[] = findApis(eventid.value);
            _eventApis.forEach((api: any) => {
                const _temp: any[] = [...api.classNames];
                const index = _temp.findIndex((className: any) => { return className == 'selected-event'; });
                if (index !== -1) {
                    _temp.splice(index, 1);
                    api.setProp('classNames', _temp);
                }
            })
        }
        eventid.value = eventid.value && eventid.value == eventId && !props.selectFirstDefault ? '' : eventId;
        refreshFullCalendarSize();
    }      
} 

// 加载事件
const getEvents = (arg: IParam, callback: Function) => {
    controller.load({arg, callback});
}

// 点击事件
const clickEvent = (arg: IParam) => {
    controller.onEventClick(arg);
    handleEventSelectStyle(arg);     
}

// 日程绘制事件
const renderEvent = (arg: IParam) => {
    if (props.selectFirstDefault && controller.isSelectFirst) {
        clickEvent(arg);
        controller.setIsSelectFirst(false);
    }
    handleEventStyle(arg);
    let data = Object.assign({ title: arg.event.title, start: arg.event.start, end: arg.event.end }, arg.event.extendedProps);
    arg.el.addEventListener('contextmenu', (event: MouseEvent) => {
      event.preventDefault();
      let calendarItem = model.calendarItems.find((_item: any) => {
          return _item.itemType == data.itemType;
      });      
      if (calendarItem && calendarItem.contextMenus) {
        let container = document.createElement('div');
        document.body.appendChild(container);
        let vueExample = createVNode(AppContextMenuContainer, {
          contextMenus: calendarItem.contextMenus,
          onContextMenuItemClick: (args:any) => {
            if (container) {
              document.body.removeChild(container);
            }
            if (args.item) {
              controller.handleContextMenuItemClick(arg, args);
            }
          },
        });
				const appInstance = App.getUIAppInstance();
				if (appInstance) {
					vueExample.appContext = appInstance.appContext;
				}        
        render(vueExample, container); 
        if (vueExample && vueExample.component && vueExample.component.exposed) {
          vueExample.component.exposed.openMenu(event)
        }
      }
    })    
}

// 图例点击事件
const legendTrigger = (itemType: string) => {
    const eventDisabled = document.getElementsByClassName('event-disabled').length;
    if (Object.keys(store.isShowLegend).length != 1 && eventDisabled == Object.keys(store.isShowLegend).length - 1 && store.isShowLegend[itemType]) {
        return;
    }
    store.isShowLegend[itemType] = !store.isShowLegend[itemType];
    refreshFullCalendar();
}

{{/if}}
{{#if (eq ctrl.calendarStyle 'TIMELINE')}}
// 时间轴点击事件
const ClickTimelineEvent = (arg: IParam) => {
    controller.onTimeLineClick(arg);
}
{{/if}}

{{#if (neq ctrl.calendarStyle 'TIMELINE')}}    
defineExpose({
    refreshFullCalendarSize,
    refreshFullCalendar
})
{{/if}}    
</script>